﻿using System;
using System.IO;
using System.IO.Pipes;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace AyuBookmark.WinForm.Pipes
{
    /// <summary>
    /// WinForm 命名管道客户端实现
    /// </summary>
    public class PipeClient : IDisposable
    {
        private readonly string _pipeName;
        private NamedPipeClientStream _clientStream;
        private bool _disposed;

        /// <summary>
        /// 初始化管道客户端
        /// </summary>
        /// <param name="pipeName">管道名称（需与服务端一致）</param>
        public PipeClient(string pipeName)
        {
            _pipeName = pipeName ?? throw new ArgumentNullException(nameof(pipeName));
        }

        /// <summary>
        /// 同步发送消息（阻塞UI线程，适合简单操作）
        /// </summary>
        public string SendMessage(string message, int timeoutMs = 3000)
        {
            try
            {
                using (var client = new NamedPipeClientStream(".", _pipeName, PipeDirection.InOut))
                {
                    client.Connect(timeoutMs);

                    // 发送消息
                    using (var writer = new StreamWriter(client, Encoding.UTF8, leaveOpen: true))
                    {
                        writer.WriteLine(message);
                        writer.Flush();
                    }

                    // 读取响应
                    using (var reader = new StreamReader(client, Encoding.UTF8, false, leaveOpen: true))
                    {
                        return reader.ReadLine();
                    }
                }
            }
            catch (TimeoutException)
            {
                MessageBox.Show($"连接超时（{timeoutMs}ms）", "管道错误", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return null;
            }
            catch (Exception ex)
            {
                MessageBox.Show($"通信失败: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return null;
            }
        }

        /// <summary>
        /// 异步发送消息（推荐用于耗时操作）
        /// </summary>
        public async Task<string> SendMessageAsync(string message, int timeoutMs = 3000, CancellationToken cancellationToken = default)
        {
            try
            {
                _clientStream = new NamedPipeClientStream(
                    ".",
                    _pipeName,
                    PipeDirection.InOut,
                    PipeOptions.Asynchronous);

                await _clientStream.ConnectAsync(timeoutMs, cancellationToken);

                // 发送消息
                using (var writer = new StreamWriter(_clientStream, Encoding.UTF8, leaveOpen: true))
                {
                    await writer.WriteLineAsync(message);
                    await writer.FlushAsync();
                }

                // 读取响应
                using (var reader = new StreamReader(_clientStream, Encoding.UTF8, false, leaveOpen: true))
                {
                    return await reader.ReadLineAsync();
                }
            }
            catch (OperationCanceledException)
            {
                MessageBox.Show("操作已取消", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                return null;
            }
            catch (Exception ex)
            {
                MessageBox.Show($"异步通信失败: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return null;
            }
            finally
            {
                Disconnect();
            }
        }

        /// <summary>
        /// 断开连接
        /// </summary>
        private void Disconnect()
        {
            try
            {
                _clientStream?.Dispose();
            }
            catch
            {
                // 忽略断开时的错误
            }
            finally
            {
                _clientStream = null;
            }
        }

        /// <summary>
        /// 释放资源
        /// </summary>
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        protected virtual void Dispose(bool disposing)
        {
            if (!_disposed)
            {
                if (disposing)
                {
                    Disconnect();
                }
                _disposed = true;
            }
        }

        ~PipeClient()
        {
            Dispose(false);
        }
    }
}